/**
 * Computer Graphics Lecture WS 2009/2010 Ulm University
 * Creator: Manuel Finckh
 * Email:   manuel.finckh@uni-ulm.de
 */

#ifndef RENDER_H
#define RENDER_H

#include "bvh.h"
#include "rtStructs.h"
#include "utils/vec.h"
#include <math.h>
#include "utils/MersenneTwister.h"

#include "scene.h"
#include "cam.h"
#include "material.h"

#define SNAPX 320
#define SNAPY 240

struct Render {
  Scene *scene;
  Cam *cam;
  BVH *accel; 

  MTRand *mtrand;
  int numThreads;

  Vec3 *image;
  Vec3 *actual;
  Vec3 *snapshot;
  int ResX, ResY; 
  int sResX, sResY;
  int nResX, nResY;
  int accum_index;
  
  int depth;
  int nr_samples;
  
  int *accum_buffer;

  Render(Scene *scene);
  ~Render();

  float* render(int shader, int snap);

  inline Vec3 shade_debug(Ray &ray, HitRec &rec);
  inline Vec3 shade_simple(Ray &ray, HitRec &rec);
  inline Vec3 shade_mirror(Ray &ray, HitRec &rec);
  inline Vec3 shade_path(Ray &ray, HitRec &rec);
  inline Vec3 shade_pathDL(Ray &ray, HitRec &rec);
  inline Vec3 shade_path_iterative(Ray &ray, HitRec &rec);
  inline void light_trace(Ray &ray, HitRec &rec, Vec3 radiance);
  inline Vec3 shade_path_SSS(Ray &ray, HitRec &rec);
  inline void shrink_accum(float &inv_accum, float &shrink);
  inline Vec3 sample_hemisphere(Vec3 normal);
  inline float BRDF(Vec3 in, Vec3 out, Vec3 normal); 
  inline float WardBRDF(Vec3 in, Vec3 out, Vec3 normal);
  inline void clearImage();
  inline Vec3 direct_illumination(Ray &ray, HitRec &rec);
  inline void accumulate(const int &x, const int &y, const Vec3 &color);
  inline float rand_exponential(const float &lambda);
  inline float schlick(const Vec3 &in, const Vec3 &n);
  inline Vec3 sample_sphere();
  inline void refract(Vec3 &out, const Vec3 &in, const Vec3 &n, float n0);
  inline void fresnel(float &R, float &T, const Vec3 &in, const Vec3 &n, float n1, float n2);
  inline float rad2deg(float rad);
  inline float dipole(Vec3 x0, Vec3 normal, Vec3 &x1, int &id);
  inline Vec3 direct_illumination(Vec3 & p, int &p_id);
};  

#endif

